﻿using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
using System.Diagnostics;

namespace a16_MTA_calcPrime_ByTask
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private bool goOn = false;
        private long curPrime = 3;

        private Stopwatch stopWatch;

        private delegate void CalcPrimeDelegate(out long prime, out long elapsed);

        public MainWindow()
        {
            InitializeComponent();
            stopWatch = new Stopwatch();
        }

        private async void StartOrStopCalc(object sender, RoutedEventArgs e)
        {
            Debug.WriteLine("Click to start or stop calc prime, threadId=" + Thread.CurrentThread.ManagedThreadId);

            if (goOn)
            {
                goOn = false;
                startOrStopBtn.Content = "Resume";
            }
            else
            {
                goOn = true;
                startOrStopBtn.Content = "Stop";

                await StartCalcAsync();
            }
        }

        private async Task StartCalcAsync()
        {
            long prime = 0;
            long elapsed = 0;

            //async 
            await Task.Run(()=>CheckNextPrime(out prime, out elapsed));
            //Debug.WriteLine("after await, prime=" + prime);


            UpdatePrimeUi(prime, elapsed);

            if (goOn)
            {
                Debug.WriteLine("Trig next calc");
                await StartCalcAsync();
            }
        }

        //run in uiThread 
        private void UpdatePrimeUi(long bigPrimeNum, long elapsedMSec)
        {
            Debug.WriteLine("Update UI, threadId=" + Thread.CurrentThread.ManagedThreadId);

            if (bigPrimeNum > 0)
            {
                bigPrime.Text = "Bigges prime: " + bigPrimeNum;
                elapsedTime.Text = "Elapsed time: " + elapsedMSec;
            }
        }

        //run in worker thread
        private void CheckNextPrime(out long prime, out long elapsed)
        {
            Debug.WriteLine("Calc next prime, curPrime=" + curPrime + ", threadId=" + Thread.CurrentThread.ManagedThreadId);

            stopWatch.Start();

            prime = 0;
            elapsed = 0;

            bool notPrime = false;

            for (long i = 3; i <= Math.Sqrt(curPrime); i++)
            {
                if (curPrime % i == 0)
                {
                    // Set not a prime flag to true.
                    notPrime = true;
                    break;
                }
            }

            // If a prime number.
            if (!notPrime)
            {
                stopWatch.Stop();
                prime = curPrime;
                elapsed = stopWatch.ElapsedMilliseconds;
            }
            //Debug.WriteLine("CheckNextPrime, prime=" + prime);

            curPrime += 2;
        }

    }
}
